from ConstraintBasedLocalSearch import ConstraintBasedLocalSearch
from LocalStateManager import LocalStateManager
import collections
import random 
from abc import abstractmethod

class MinConflicts(ConstraintBasedLocalSearch):

	def __init__(self):
		self.localStateManager = None

	def minConflicts(self, maxSteps=10000):
		random.seed()
		conflictedVars = []
		for i in range(maxSteps):
			if self.localStateManager.evalutateState(self.localStateManager.currentState)==0:
				return (self.localStateManager.currentState, i+1, self.localStateManager.evalutateState(self.localStateManager.currentState))
			conflictedVars = self.conflictedVariables(self.localStateManager.currentState)
			if len(conflictedVars)!=0:
				var = conflictedVars[random.randint(0, len(conflictedVars)-1)]
				value = self.conflicts(var, self.localStateManager.currentState)
				if value is not None:
					self.localStateManager.modifyState(var, value)
			#print "CONFLICTS: " + str(self.localStateManager.evalutateState(self.localStateManager.currentState))
		return (self.localStateManager.currentState, i+1, self.localStateManager.evalutateState(self.localStateManager.currentState))
			
	@abstractmethod
	def conflicts(self, var, state):
		copy_state = list(state)
		currentValue = None
		currentConflicts = self.localStateManager.evalutateState(copy_state)
		for i in range(len(copy_state)):
			#switching column between i and var
			temp = copy_state[var]
			copy_state[var] = copy_state[i]
			copy_state[i] = temp
			if currentConflicts > self.localStateManager.evalutateState(copy_state):
				currentConflicts = self.localStateManager.evalutateState(copy_state)
				currentValue = copy_state[var]
			#putting them back
			copy_state[i] = copy_state[var]
			copy_state[var] = temp
		return currentValue
		
	@abstractmethod
	def conflictedVariables(self, state):
		conflicted = []
		for i in range(len(state)):
			if not (i == len(state)-1):
				if (state[i]+1 == state[i+1] or state[i] == state[i+1]+1) and (state[i] not in conflicted):
					conflicted += [state[i]]
		lst = collections.Counter(state).most_common()
		if len(lst)!=0:
			for i in lst:
				if i[1] > 1 and (i[0] not in conflicted):
					conflicted += [i[0]]
		return conflicted
		
	def initStateManager(self):
		self.localStateManager = LocalStateManager(None)
		self.localStateManager.generateInitState()